﻿using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Threading;
using System.Windows;
using Infrastructure.Interfaces;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.ServiceLocation;

namespace Infrastructure.BaseClasses
{
    /// <summary>
    /// Klasa bazowa dla ViewModel
    /// </summary>
    public abstract class ViewModelBase : DependencyObject, INotifyPropertyChanged
    {
        #region Events
        protected AutoResetEvent _pauseCurrentThread = new AutoResetEvent(false);
        public event EventHandler<EventArgs> EditViewClosing;
        #endregion

        #region Variables
        protected IEventAggregator _eventAggregator;
        protected IErrorWindow _errorWindow;
        private bool _isBusy;
        #endregion

        #region Constructor
        protected ViewModelBase()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                _eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
                _errorWindow = ServiceLocator.Current.GetInstance<IErrorWindow>();
            }
        }
        #endregion
        
        #region Properties
        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                _isBusy = value;
                NotifyOfPropertyChange(() => IsBusy);
            }
        }
        #endregion

        #region Methods
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Publikuj zmianę w propercji
        /// </summary>
        /// <param name="propName">nazwa propercji, w której nastąpiła zmiana</param>
        public virtual void RaisePropertyChanged(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        protected string GetPropertyName<TProperty>(Expression<Func<TProperty>> property)
        {
            var lambda = (LambdaExpression)property;

            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
            }
            else memberExpression = (MemberExpression)lambda.Body;

            return memberExpression.Member.Name;
        }

        public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
        {
            RaisePropertyChanged(GetPropertyName(property));
        }
        #endregion

        protected void ShowErrorMessage(string message)
        {
            if(_errorWindow != null)
            {
                _errorWindow.Message = message;
                _errorWindow.Show();
            }
        }
        protected void ShowErrorMessage(Exception exception)
        {
            if (_errorWindow != null)
            {
                _errorWindow.Exception = exception;
                _errorWindow.Show();
            }
        }
        protected void Close()
        {
            EventHandler<EventArgs> windowHandler = EditViewClosing;
            if (windowHandler != null)
                windowHandler(this, new EventArgs());
        }
        #endregion


    }
}
